/*******************************************************************************
 * Software Name : Android Simple Downloader
 *
 * Copyright © 2012 Rinvay Tang
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

package com.rinvay.network.filedownload.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

import com.rinvay.utils.logger.Log;

public class DownloadTask
{
    private static final String TAG = "DownloadTask";

    private long _id = 0;

    private String uuid = null;

    private String resourceUrl = null;

    private String fileDirectory = null;

    private String fileName = null;

    private boolean isFinished = false;

    private int size = -1;

    private int threadSize = 1;

    private HashMap<String, String> connProperties = null;

    private List<Part> parts;
    /**
     * 上一次统计的已下载长度，用于计算速度
     */
    private int preLength = 0;

    private int state = -1;

    /**
     * k/s
     */
    private int speed;

    public DownloadTask(String url, String fileDirectory, String fileName,
            int threadSize) {
        this.uuid = UUID.randomUUID().toString();
        this.resourceUrl = url;
        this.fileDirectory = fileDirectory;
        this.fileName = fileName;
        this.threadSize = threadSize;
        this.parts = new ArrayList<Part>();

    }

    public synchronized boolean updateTaskFinished() {
        isFinished = true;
        for (Part p : parts) {
            if (!p.isPartFinished()) {
                isFinished = false;
                break;
            }
        }
        return isFinished;
    }

    public boolean isTaskFinished() {
        return isFinished;
    }

    public void setTaskFinished(boolean finished) {
        isFinished = finished;
    }

    public boolean isTaskFailed() {
        boolean hasPartFailed = false;
        for (Part p : parts) {
            if (p.getState() == DownloadTask.STATE_FAILED) {
                hasPartFailed = true;
                continue;
            } else if (p.getState() == DownloadTask.STATE_FINISHED) {
                continue;
            } else {
                return false;
            }
        }
        Log.i(TAG, fileName + " task failed " + hasPartFailed);
        return hasPartFailed;
    }

    public boolean isDownloading() {
        return this.state == STATE_CONNECTING
                || this.state == STATE_DOWNLOADING;
    }

    public long getId() {
        return _id;
    }

    public void setId(long _id) {
        this._id = _id;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getUUId() {
        return uuid;
    }

    public String getResourceUrl() {
        return resourceUrl;
    }

    public String getFileDirectory() {
        return fileDirectory;
    }

    public String getFileName() {
        return fileName;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        switch (state)
        {
//	    case STATE_STARTED:
        case STATE_CONNECTING:
        case STATE_DOWNLOADING:
        case STATE_PAUSED:
            this.state = state;
            break;
        case STATE_FAILED:
        case STATE_FINISHED:
            for (Part p : parts) {
                if (p.getState() != state) {
                    return;
                }
            }
            this.state = state;
            break;

        }
    }

    public void setThreadSize(int threadSize) {
        this.threadSize = threadSize;
    }

    public int getThreadSize() {
        return this.threadSize;
    }

    public List<Part> getParts() {
        return parts;
    }

    public int getCurLength() {
        int length = 0;
        for (Part p : parts) {
            length += p.getCurLength();
        }
        return length;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public int getPreLength() {
        return preLength;
    }

    public void setPreLength(int preLength) {
        this.preLength = preLength;
    }

    public void setConnProperty(String name, String value) {
        if (connProperties == null) {
            this.connProperties = new HashMap<String, String>();
        }
        connProperties.put(name, value);
    }

    public HashMap<String, String> getConnProperties() {
        return connProperties;
    }

    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("DownLoadTask[").append("name:" + fileName + "| ")
                .append("size:" + size + "| ")
                .append("isfinished:" + isFinished + "| ")
                .append("curlen:" + preLength + "| ")
                .append("thread:" + threadSize + "| ")
                .append("uuid:" + uuid + "| ")
                .append("url:" + resourceUrl + "").append("]");
        return builder.toString();
    }

    /**
     * 等待
     */
    public static final int STATE_WAITING = 0;
    /**
     * 开始连接
     */
    public static final int STATE_CONNECTING = STATE_WAITING + 1;
    /**
     * 正在下载
     */
    public static final int STATE_DOWNLOADING = STATE_CONNECTING + 1;
    /**
     * 暂停
     */
    public static final int STATE_PAUSED = STATE_DOWNLOADING + 1;
    /**
     * 完成
     */
    public static final int STATE_FINISHED = STATE_PAUSED + 1;
    /**
     * 失败
     */
    public static final int STATE_FAILED = STATE_FINISHED + 1;
}
